package com.sunchangpeng.wechat.mp.qrcode;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.sunchangpeng.wechat.core.WechatClient;
import com.sunchangpeng.wechat.mp.EndpointProvider;
import com.sunchangpeng.wechat.mp.MpAppSetting;
import com.sunchangpeng.wechat.mp.MpWechatClientFactory;
import lombok.Builder;
import lombok.Data;

import static com.sunchangpeng.wechat.core.utils.URLUtils.encode;

public class QRcodes {
    private WechatClient wechatClient;

    public void setWechatClient(WechatClient wechatClient) {
        this.wechatClient = wechatClient;
    }

    public static QRcodes with(MpAppSetting appSetting) {
        QRcodes qrcodes = new QRcodes();
        qrcodes.setWechatClient(MpWechatClientFactory.getInstance().with(appSetting));
        return qrcodes;
    }

    /**
     * 创建临时二维码
     */
    public Ticket temporary(Integer expires, int sceneId) {
        verifySceneId(sceneId);

        String url = EndpointProvider.get("url.ticket.create");

        TicketRequest request = TicketRequest.builder()
                .expireSeconds(expires)
                .actionName("QR_SCENE")
                .actionInfo(new ActionInfo(sceneId))
                .build();

        String response = wechatClient.getTextWithToken(url, JSON.toJSONString(request));
        return JSON.parseObject(response, Ticket.class);
    }

    /**
     * 创建临时二维码
     */
    public Ticket temporary(Integer expires, String sceneStr) {
        verifySceneStr(sceneStr);

        String url = EndpointProvider.get("url.ticket.create");

        TicketRequest request = TicketRequest.builder()
                .expireSeconds(expires)
                .actionName("QR_STR_SCENE")
                .actionInfo(new ActionInfo(sceneStr))
                .build();

        String response = wechatClient.getTextWithToken(url, JSON.toJSONString(request));
        return JSON.parseObject(response, Ticket.class);
    }

    /**
     * 创建永久二维码
     */
    public Ticket permanent(int sceneId) {
        verifySceneId(sceneId);

        String url = EndpointProvider.get("url.ticket.create");
        TicketRequest request = TicketRequest.builder()
                .actionName("QR_LIMIT_SCENE")
                .actionInfo(new ActionInfo(sceneId))
                .build();

        String response = wechatClient.getTextWithToken(url, JSON.toJSONString(request));
        return JSON.parseObject(response, Ticket.class);
    }

    /**
     * 创建永久二维码
     */
    public Ticket permanent(String sceneStr) {
        verifySceneStr(sceneStr);

        String url = EndpointProvider.get("url.ticket.create");
        TicketRequest request = TicketRequest.builder()
                .actionName("QR_LIMIT_STR_SCENE")
                .actionInfo(new ActionInfo(sceneStr))
                .build();

        String response = wechatClient.getTextWithToken(url, JSON.toJSONString(request));
        return JSON.parseObject(response, Ticket.class);
    }

    private void verifySceneId(int sceneId) {
        if (sceneId < 1 || sceneId > 100000) {
            throw new IllegalArgumentException("sceneId shall be between 1 and 100000.");
        }
    }

    private void verifySceneStr(String sceneStr) {
        if (sceneStr == null || sceneStr.length() == 0 || sceneStr.length() > 64) {
            throw new IllegalArgumentException("sceneStr shall not be empty and the length shall be less than 64.");
        }
    }

    /**
     * 使用ticket换取二维码
     */
    public byte[] showqrcode(String ticket) {
        String url = EndpointProvider.get("url.ticket.qrcode");
        return wechatClient.getBytes(String.format(url, encode(ticket)));
    }

    @Data
    public static class Ticket {
        private String ticket;

        @JSONField(name = "expire_seconds")
        private int expiresIn;

        private String url;
    }

    @Data
    public static class ActionInfo {
        private Scene scene;

        public ActionInfo(Integer sceneId) {
            this.scene = new Scene(sceneId, null);
        }

        public ActionInfo(String sceneStr) {
            this.scene = new Scene(null, sceneStr);
        }
    }

    @Data
    public static class Scene {
        @JSONField(name = "scene_id")
        private Integer sceneId;

        @JSONField(name = "scene_str")
        private String sceneStr;

        public Scene(Integer sceneId, String sceneStr) {
            this.sceneId = sceneId;
            this.sceneStr = sceneStr;
        }
    }


    @Data
    @Builder
    public static class TicketRequest {
        //该二维码有效时间，以秒为单位。 最大不超过2592000（即30天），此字段如果不填，则默认有效期为30秒
        @JSONField(name = "expire_seconds")
        private Integer expireSeconds;

        @JSONField(name = "action_name")
        private String actionName;

        @JSONField(name = "action_info")
        private ActionInfo actionInfo;
    }
}
